﻿using System;
using System.Linq;
using Microsoft.AspNetCore.Http;
using net.xBei.Helper;
using UAParser;

namespace net.xBei.WebApi.Helper {
    /// <summary>
    /// 
    /// </summary>
    public static class RequestHelper {
        /// <summary>
        /// 是否本地请求
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static bool IsLocal(this HttpRequest request) {
            if (!request.Host.HasValue
                || (request.Host.Host != "127.0.0.1" && request.Host.Host.ToLower() != "localhost")) {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string GetHeader(this HttpRequest request, string name, string dv)
            => request.Headers.TryGetValue(name, out var v) ? v.ToString() : dv;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static int GetHeader(this HttpRequest request, string name, int dv)
            => request.Headers.TryGetValue(name, out var v) ? v.ToString().GetInt(dv) : dv;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static IFormFileCollection? GetFiles(this HttpRequest request)
            => request.ContentLength > 0 ? request.Form.Files : default;
        /// <summary>
        /// 通过“User-Agent”获取客户端信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static ClientInfo? GetClientInfo(this HttpRequest request) {
            var ua = GetHeader(request, "User-Agent", string.Empty);
            if (string.IsNullOrWhiteSpace(ua)) return null;
            var uaParser = Parser.GetDefault();
            return uaParser.Parse(ua);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="ua"></param>
        /// <returns></returns>
        public static ClientInfo? ParseUserAgent(this HttpRequest request, string ua) {
            if (string.IsNullOrWhiteSpace(ua)) return null;
            var uaParser = Parser.GetDefault();
            return uaParser.Parse(ua);
        }
        static string[] DpjDeviceList = new[] { "DpjOrderTools", "DepogaApiTool" };
        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public static string GetDevice(this ClientInfo info) {
            //DepogaApiTool (Windows 10.0.22000) node-fetch/1.0
            //DpjOrderTools/1.0.20 (Windows NT;https://www.depoga.com/tools)
            return info == null
                ? string.Empty
                : (DpjDeviceList.Any(s => info.String.Contains(s))
                    ? "DepogaApiTool"
                    : info.UA.ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool HostIsEquals(this HttpRequest request, string uri) => IsEquals(request.Host, uri);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool IsEquals(this HostString host, string uri)
            => host.HasValue && (Uri.TryCreate(uri, UriKind.RelativeOrAbsolute, out var result) && IsEquals(host, result));
        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool IsEquals(this HostString host, Uri uri) => host.Host.Equals(uri.Host, StringComparison.OrdinalIgnoreCase);
        #region Query
        /// <summary>
        /// 从Query中获取值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回<see cref="string.Empty"/></returns>
        public static string GetQueryValue(this HttpRequest request, string name, string? dv = default)
            => GetQueryValue(request.Query, name, dv);
        /// <summary>
        /// 从Query中获取<see cref="int"/>值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static int GetIntFromQuery(this HttpRequest request, string name, int? dv = default)
            => GetIntFromQuery(request.Query, name, dv);
        /// <summary>
        /// 从Query中获取<see cref="long"/>值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static long GetLongFromQuery(this HttpRequest request, string name, long? dv = default)
            => GetLongFromQuery(request.Query, name, dv);
        /// <summary>
        /// 从Query中获取<see cref="float"/>值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static float GetFloatFromQuery(this HttpRequest request, string name, float? dv = default)
            => GetFloatFromQuery(request.Query, name, dv);
        /// <summary>
        /// 从Query中获取<see cref="bool"/>值，解析顺序："true"、"false"、"yes"、"no"、"on"、"off"。
        /// 如果值是数值，非0为True，0为False。
        /// 如果无法解析，会返回<paramref name="dv"/>
        /// </summary>
        /// <param name="request"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“false”</returns>
        public static bool GetBooleanFromQuery(this HttpRequest request, string name, bool? dv = default)
            => GetBooleanFromQuery(request.Query, name, dv);
        /// <summary>
        /// 从Query中获取值
        /// </summary>
        /// <param name="query"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回<see cref="string.Empty"/></returns>
        public static string GetQueryValue(this IQueryCollection query, string name, string? dv = default)
            => (query.TryGetValue(name, out var v) ? v.First() : dv) ?? string.Empty;
        /// <summary>
        /// 从Query中获取<see cref="int"/>值
        /// </summary>
        /// <param name="query"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static int GetIntFromQuery(this IQueryCollection query, string name, int? dv = default)
            => int.TryParse(GetQueryValue(query, name, "0"), out var v) ? v : (dv ?? 0);
        /// <summary>
        /// 从Query中获取<see cref="long"/>值
        /// </summary>
        /// <param name="query"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static long GetLongFromQuery(this IQueryCollection query, string name, long? dv = default)
            => long.TryParse(GetQueryValue(query, name, "0"), out var v) ? v : (dv ?? 0);
        /// <summary>
        /// 从Query中获取<see cref="float"/>值
        /// </summary>
        /// <param name="query"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“0”</returns>
        public static float GetFloatFromQuery(this IQueryCollection query, string name, float? dv = default)
            => float.TryParse(GetQueryValue(query, name, "0"), out var v) ? v : (dv ?? 0);
        /// <summary>
        /// 从Query中获取<see cref="bool"/>值，解析顺序："true"、"false"、"yes"、"no"、"on"、"off"。
        /// 如果值是数值，非0为True，0为False。
        /// 如果无法解析，会返回<paramref name="dv"/>
        /// </summary>
        /// <param name="query"></param>
        /// <param name="name"></param>
        /// <param name="dv"></param>
        /// <returns>如果无法获取数据且<paramref name="dv"/>未指定，会返回“false”</returns>
        public static bool GetBooleanFromQuery(this IQueryCollection query, string name, bool? dv = default) {
            string v = GetQueryValue(query, name);
            if (string.IsNullOrWhiteSpace(v)) {
                return false;
            }
            if (bool.TryParse(v, out var b)) {
                return b;
            }
            if (v.Equals("yes", StringComparison.OrdinalIgnoreCase) || v.Equals("on", StringComparison.OrdinalIgnoreCase)) {
                return true;
            }
            if (v.Equals("no", StringComparison.OrdinalIgnoreCase) || v.Equals("off", StringComparison.OrdinalIgnoreCase)) {
                return false;
            }
            if (int.TryParse(v, out var i)) {
                return i != 0;
            }
            return dv ?? false;
        }
        #endregion
    }
}
